package com.airspyar;

import java.util.Vector;

import android.app.Activity;
import android.app.Service;
import android.graphics.PixelFormat;
import android.hardware.SensorManager;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.Toast;

import com.airspyar.R;

public class AirSpyActivity extends Activity{
    
	private final static int LOGLEVEL=3;
	public final static boolean LOG_INFO=LOGLEVEL>2;
	public final static boolean LOG_WARN=LOGLEVEL>1;
	public final static boolean LOG_ERROR=LOGLEVEL>0;
	
	private ObserverDataHolder observerDataHolder;
	private PlanesDataProvider planesDataProvider;
	private PlaneSelector planeSelector;
	private ImageButton lockButton;
	private Display display;
	private Handler handler;
	private boolean selectorPausedByUser=false;
	
	
	private void restoreState(Bundle savedInstanceState){
		if(savedInstanceState==null)
			return;
		
		if(savedInstanceState.containsKey("visibility")){
			planesDataProvider.setVisibilityDistance(savedInstanceState.getInt("visibility"));
		}
		
		if(savedInstanceState.containsKey("previewEnabled")){
			if(!savedInstanceState.getBoolean("previewEnabled"))
				display.getCamera().hide();
		}
	}
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFormat(PixelFormat.RGBA_8888);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_DITHER);
        
        setContentView(R.layout.main);

        display=new Display(this);
        
        lockButton=(ImageButton)findViewById(R.id.lockButton);
        lockButton.setOnClickListener(new OnClickListener(){
			@Override
			public void onClick(View v) {
				if(selectorPausedByUser){
					planeSelector.setPaused(false);
					lockButton.setImageResource(R.drawable.unlock);
					selectorPausedByUser=false;
				}else{
					planeSelector.setPaused(true);
					lockButton.setImageResource(R.drawable.lock);
					selectorPausedByUser=true;
				}
				
			}
        });
        
        handler=new Handler(){
        	@Override
        	public void handleMessage(Message msg){
        		switch(msg.what){
        		case PlaneSelector.PLANE_SELECTED_MESSAGE:
        			DetailedFlightState state=(DetailedFlightState)msg.obj;
            		display.showState(state);
            		
            		if(LOG_INFO)
            			Log.i("Msg from PlaneSelector", "Plane selected: "+state.getCallsign());
            	break;
        		case PlaneSelector.NOTHING_SELECTED_MESSAGE:
            		display.hideAll();
            		
            		if(LOG_INFO)
            			Log.i("Msg from PlaneSelector", "Nothing selected");
            	break;
        		case PlanesDataProvider.DATA_UPDATE_MESSAGE:
        			display.hideLoadingDialog();
        			
        			int planesCount=((Vector<?>)msg.obj).size();
        			
            		if(LOG_INFO)
            			Log.i("Msg from PlanesDataProvider", ""+planesCount+" planes found!");
        			
        			if(planesCount==0){
        				Toast.makeText(AirSpyActivity.this, "No planes found (range: "+planesDataProvider.getVisibilityDistance()+"km)!", Toast.LENGTH_SHORT).show();
        				planeSelector.setPaused(true);
        				
                		if(LOG_INFO)
                			Log.i("Msg from PlanesDataProvider", "No planes found, PlaneSelector paused");
        			}
        			else if(planeSelector.isPaused() &! selectorPausedByUser){
        				planeSelector.setPaused(false);
        				
                		if(LOG_INFO)
                			Log.i("Msg from PlanesDataProvider", "Planes found, PlaneSelector started!");
        			}
            	break;
        		case PlanesDataProvider.SYNCHRONIZATION_ERROR_MESSAGE:
    				Toast.makeText(AirSpyActivity.this, "Could not synchronize with flightradar24!", Toast.LENGTH_SHORT).show();
    				
            		if(LOG_ERROR)
            			Log.e("Msg from PlanesDataProvider", "Could not synchronize with flightradar24!");
        		}
        	}
        };
        

        observerDataHolder=new ObserverDataHolder((LocationManager)this.getSystemService(Service.LOCATION_SERVICE), (SensorManager)this.getSystemService(Service.SENSOR_SERVICE));
        planesDataProvider=new PlanesDataProvider(handler, observerDataHolder);
        planeSelector=new PlaneSelector(handler, observerDataHolder, planesDataProvider);
        restoreState(savedInstanceState);

        planesDataProvider.start();
		planeSelector.start();
		
		display.getRadar().setDataProviders(observerDataHolder, planesDataProvider);
    }
    

	@Override
	public void onResume() {
		super.onResume();
		
		observerDataHolder.initialize();

		display.showLoadingDialog();
		
		planesDataProvider.setPaused(false);
		
		
		if(LOG_INFO)
			Log.i("onReasume", "PlanesDataProvider started");
	}
	
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if(keyCode==KeyEvent.KEYCODE_FOCUS){
			lockButton.performClick();
			return true;
		}
		return super.onKeyDown(keyCode, event);
	}

	@Override
	public void onPause() {
		planeSelector.setPaused(true);
		planesDataProvider.setPaused(true);
		
		observerDataHolder.release();
		
		if(LOG_INFO)
			Log.i("onPause", "PlanesDataProvider paused");		
		
		super.onPause();
	}
	
	@Override
	public void onSaveInstanceState(Bundle outState) {
		outState.putInt("visibility", planesDataProvider.getVisibilityDistance());
		outState.putBoolean("previewEnabled", display.getCamera().isPreviewActive());
		super.onSaveInstanceState(outState);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		this.getMenuInflater().inflate(R.menu.menu, menu);
		if(!display.getCamera().isPreviewActive())
			menu.findItem(R.id.menu_camera).setTitle(R.string.preview_start);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch(item.getItemId()){
		case R.id.menu_visibility:
			VisibilityDialog dialog=new VisibilityDialog(this, planesDataProvider.getVisibilityDistance());
			dialog.setTitle("Set visibility");
			dialog.setResultListener(
				new VisibilityDialog.ResultListener(){
					@Override
					public void onVisibilityChanged(int newVisibility){
						planesDataProvider.setVisibilityDistance(newVisibility);
						planesDataProvider.invalidate();
						
						if(LOG_INFO)
							Log.i("Visibility changed", "Visibility set to "+newVisibility+"km");
					}
				}
			);
			dialog.show();
			return true;
		case R.id.menu_camera:
			CameraView camera=display.getCamera();
			if(camera.isPreviewActive()){
				camera.hide();
				item.setTitle(R.string.preview_start);
			}else{
				camera.show();
				item.setTitle(R.string.preview_stop);
			}
			return true;
		}
		
		return super.onOptionsItemSelected(item);
	}

	@Override
	public void onDestroy() {
		planesDataProvider.kill();
		planeSelector.kill();
		
		if(LOG_INFO)
			Log.i("onDestroy", "All threads stopped");
		
		super.onDestroy();
	}
}